home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 11 / FM Towns Free Software Collection 11.iso / t_os / tool / artemis2 / src / imgwin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-01  |  12.8 KB  |  494 lines

  1. /*====================================================
  2.                       ARTemis
  3.                    (version 1.3)
  4.              FM-TOWNS 用ペイントツール
  5.  
  6.                  by 松内 良介 1994
  7. ====================================================*/
  8. #define MODULE_IMGWIN
  9. /*
  10.     imgwins.c
  11.  
  12.     int    imageWINfunc(kobj, messId, argc, pev, trigger)
  13.     int    imageSBARfunc(kobj, messId, argc, pev, trigger)
  14.     int    ImageEraseDBtnProc(int kobj)
  15.  
  16. static int draw_line(IMWIN *win, POINT *first, int type)
  17. static int draw_freeline(IMWIN *win, POINT *first, int type)
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <winb.h>
  24. #include <te.h>
  25. #include <fntb.h>
  26. #include <gui.h>
  27. #include <egb.h>
  28. #include <wgb.h>
  29. #include <msdos.cf>
  30. #include "art.h"
  31. #include "guisub.h"
  32. #include "wgbmac.H"
  33. #include "alert.h"
  34.  
  35. #include "imagewin.h"
  36. #include "imgwin.h"
  37. #include "pensel.h"
  38. #include "colsel.h"
  39. #include "fifo.h"
  40. #include "subgrp.h"
  41. #include "desktop.h"
  42. #include "copy.h"
  43.  
  44. int    idImageWin = -1 ;
  45. int    idImageHSBar = -1 ;
  46. int    idImageVSBar = -1 ;
  47. int    idImageTitleDBtn = -1 ;
  48. int    idImageTitleMsg = -1 ;
  49. int    idImageEraseDBtn = -1 ;
  50. int    idImageBtn = -1 ;
  51.  
  52. /*--------------------------------------------------------*/
  53. /*                   部品の呼び出し関数                   */
  54. /*--------------------------------------------------------*/
  55.  
  56. static    int        draw_freeline(IMWIN *win, EVENT* first_ev, int type);
  57. static    int        draw_line(IMWIN *win, POINT *first, int type);
  58.  
  59.   /* ■画像ウィンドウの呼び出し関数■ */
  60.  
  61.         /*    initDataIMGWIN:imageWIN:MJ_WINDOWL40の呼び出し関数    */
  62.     int    imageWINfunc(kobj, messId, argc, pev, trigger)
  63.     int        kobj ;
  64.     int        messId ;
  65.     int        argc ;
  66.     EVENT    *pev ;
  67.     int        trigger ;
  68.     {
  69.         IMWIN *win;
  70.         WINCLIP *clipStack;
  71.         win = imagewin_getWinFromPart(kobj);
  72.         if (win == NULL)
  73.             return -1;
  74.  
  75.       /* MM_SHOW メッセージへの応答 */
  76.         if (messId == MM_SHOW)
  77.             imagewin_updateScr(win);
  78.  
  79.       /* MM_UPDATE(リサイズ)への応答 */
  80.         else if (messId == MM_UPDATE)
  81.             imagewin_resize(win, TRUE);
  82.  
  83.       /* アクティブになった時 */
  84.         else if (messId == MM_WAKE)
  85.         {
  86.             HYPER Ht;
  87.             WINCLIP *clipStack;
  88.             OBJHYP(win->titlebar).clr.back = DARKGRAY;
  89.             OBJHYP(win->titlemsg).clr.ch   = WHITE;
  90.             OBJHYP(win->erasebtn).clr.back = DARKGRAY;
  91.             WIN_beginUpDateObj(win->titlebar, &clipStack);
  92.             MMI_SendMessage(win->titlebar, MM_SHOW, 0);
  93.             MMI_SendMessage(win->titlemsg, MM_SHOW, 0);
  94.             MMI_SendMessage(win->erasebtn, MM_SHOW, 0);
  95.             WIN_endUpDateObj(clipStack);
  96.             imagewin_setCurrentWin(win);
  97.         }
  98.  
  99.       /* ノンアクティブになった時 */
  100.         else if (messId == MM_SLEEP)
  101.         {
  102.             HYPER Ht;
  103.             WINCLIP *clipStack;
  104.             OBJHYP(win->titlebar).clr.back = GRAY;
  105.             OBJHYP(win->titlemsg).clr.ch   = BLACK;
  106.             OBJHYP(win->erasebtn).clr.back = GRAY;
  107.             WIN_beginUpDateObj(win->titlebar, &clipStack);
  108.             MMI_SendMessage(win->titlebar, MM_SHOW, 0);
  109.             MMI_SendMessage(win->titlemsg, MM_SHOW, 0);
  110.             MMI_SendMessage(win->erasebtn, MM_SHOW, 0);
  111.             WIN_endUpDateObj(clipStack);
  112.             if (imagewin_getCurrentWin() == win)
  113.                 imagewin_setCurrentWin(NULL);
  114.         }
  115.  
  116.       // マウスボタンに対する応答
  117.         else if (messId == MM_MOUSEON && (pev->shift&SLEFTBTN) != 0)
  118.         {
  119.             int ret;
  120.             int tool = toolbox_getCurrentTool();
  121.             switch (tool)
  122.             {
  123.                 case TOOL_FPSET:
  124.                 case TOOL_FLINE:
  125.                 case TOOL_KOSURI:
  126.                 case TOOL_PAINT:
  127.                 case TOOL_NIZIMI:
  128.                 case TOOL_BOKASI:
  129.                 case TOOL_SAND:
  130.                     ret = draw_freeline(win, pev, tool);
  131.                     break;
  132.                 case TOOL_LINE:
  133.                     ret = draw_line(win, (POINT*)&pev->info, 0);
  134.                     break;
  135.                 case TOOL_BOXFILL:
  136.                     ret = draw_line(win, (POINT*)&pev->info, 2);
  137.                     break;
  138.                 case TOOL_COPY:
  139.                     ret = input_rectarea(win, pev);
  140.                     break;
  141.                 case TOOL_POLYGONCOPY:
  142.                     ret = input_polygonarea(win,pev);
  143.                     break;
  144.                 case TOOL_POLYGONFILL:
  145.                     ret = cmd_polygonfill(win,pev);
  146.                     break;
  147.                 case TOOL_ZOOMCOPY:
  148.                     ret = cmd_rectzoomcopy(win,pev);
  149.                     break;
  150.             }
  151.             return ret;
  152.         }
  153.         
  154.         else if (messId == MM_MOUSEON && (pev->shift&SRIGHTBTN) != 0)
  155.         {
  156.             // スポイト操作
  157.             POINT mospt = *(POINT*)&pev->info;
  158.             if (imagewin_PtInPic(win,&mospt))
  159.             {
  160.                 POINT ptPic;
  161.                 imagewin_getPosFromMos(win,&mospt,&ptPic);
  162.                 PIXEL pix;
  163.                 pic_getPixelXy(win->pic, ptPic.x,ptPic.y, &pix);
  164.                 colsel_setCurPixel(&pix);
  165.             }
  166.         }
  167.         return NOERR ;
  168.     }
  169.  
  170.   /* ■画像ウィンドウのスクロールバー■ */
  171.  
  172.         /*    initDataIMGWIN:imageSBARhori:MJ_SCRLL40の呼び出し関数    */
  173.         /*    initDataIMGWIN:imageSBARvert:MJ_SCRLL40の呼び出し関数    */
  174.     int    imageSBARfunc(kobj, messId, argc, pev, trigger)
  175.     int        kobj ;
  176.     int        messId ;
  177.     int        argc ;
  178.     EVENT    *pev ;
  179.     int        trigger ;
  180.     {
  181.         IMWIN *win;
  182.         if ((win = imagewin_getWinFromPart(kobj)) == NULL)
  183.             return -1;
  184.         imagewin_updateBuf(win);
  185.         imagewin_updateScr(win);
  186.         return NOERR ;
  187.     }
  188.  
  189. int    ImageEraseDBtnProc(int kobj)
  190. // initDataZIMGWIN:idImageEraseDBtn:MJ_DBUTTONL40の呼び出し関数
  191. {
  192.     IMWIN *win;
  193.     if ((win = imagewin_getWinFromPart(kobj)) == NULL)
  194.         return -1;
  195.     char buf[250];
  196.     sprintf(buf, "画像 %s のウィンドウをクローズします。"
  197.             "画像データは破棄されますが、よろしいですか?",
  198.             (win->fname[0]==0 ? "<名称未定>" : win->fname));
  199.     if (dispCheckMessage("画像ウィンドウを閉じる", buf, "続行") == 0)
  200.     {
  201.         imagewin_unlink(win);
  202.         imagewin_destroy(win);
  203.         if (imagewin_getCurrentWin() == win)
  204.             imagewin_setCurrentWin(NULL);
  205.     }
  206.     return NOERR ;
  207. }
  208.  
  209.  
  210. /*--------------------------------------------------------*/
  211. /*                   自由曲線による描画                   */
  212. /*--------------------------------------------------------*/
  213.  
  214. static int pen_ofsx, pen_ofsy;
  215.  
  216. static void _putPixel(IMWIN *win, POINT *pt)
  217. /* 画像内の位置 pt に点を置く */
  218. {
  219.     PIXEL pixel;
  220.     colsel_getPixel(&pixel);
  221.     pic_psetpen(win->pic,pt->x,pt->y,pensel_curpen(),&pixel);
  222. }
  223.  
  224. static void _flushPointBuf(IMWIN *win, FIFO *points, int tooltype)
  225. {
  226.     if (fifo_isEmpty(points))
  227.         return;
  228.     pic_beginUpDate(win->pic);
  229.   /* 4座標ずつまとめて処理 */
  230.     int i;
  231.     for (i=0; i<4; i++)
  232.     {
  233.         if (fifo_isEmpty(points))
  234.             break;
  235.         POINT mosp, imgp;
  236.       /* マウスカーソル位置が画像内のどこであるかを得る */
  237.         fifo_get(points, &mosp);
  238.         imagewin_getPosFromMos(win, &mosp, &imgp);
  239.         PIXEL pixel;  colsel_getPixel(&pixel);
  240.         Pen pen = pensel_curpen();
  241.         switch(tooltype)
  242.         {
  243.         case TOOL_NIZIMI:
  244.             pic_blot(win->pic, imgp.x,imgp.y,2,paramNizimi, &pixel);
  245.             break;
  246.         case TOOL_KOSURI:
  247.             pic_kosuriDrag(win->pic,imgp.x-pen_ofsx,imgp.y-pen_ofsy,
  248.                             paramKosuri);
  249.             break;
  250.         case TOOL_BOKASI:
  251.             pic_diffusePen(win->pic,imgp.x,imgp.y,pen);
  252.             break;
  253.         case TOOL_SAND:
  254.             pic_sandPen(win->pic,imgp.x,imgp.y,pen);
  255.             break;
  256.         default:
  257.             _putPixel(win, &imgp);
  258.             break;
  259.         }
  260.     }
  261.   /* 画面(とユーザー領域バッファ)に画像の更新部分を転送 */
  262.     FRAME updatefr;
  263.     pic_endUpDate(win->pic, &updatefr);
  264.     imagewin_updateScrPart(win, &updatefr);
  265. }
  266.  
  267. static    int draw_freeline(IMWIN *win, EVENT* first_ev, int type)
  268. /* first:最初のマウス座標 */
  269. {
  270.     imagewin_storeUndo(win);
  271.     EVENT *ev = first_ev;
  272.     POINT cp = *(POINT*)&first_ev->info;
  273.     POINT lastp = cp;
  274.   // FIFOバッファの作成
  275.     FIFO *points = fifo_new(sizeof(POINT));
  276.     if (points == NULL)
  277.     {
  278.         dispAlertMessage("メモリ不足です",
  279.             "描画処理を行うためのメモリ領域が不足しています。"
  280.             "不要な画像ウィンドウをクローズしてみてください");
  281.         return NOERR;
  282.     }
  283.   // 最初の点に関する処理
  284.     switch(type)
  285.     {
  286.     case TOOL_KOSURI: {
  287.         char *graypat;  int wid,ht;
  288.         pensel_getPattern(&graypat, &wid,&ht,&pen_ofsx,&pen_ofsy);
  289.         POINT pt;  imagewin_getPosFromMos(win, &cp, &pt);
  290.         pic_kosuriStart(win->pic,pt.x-pen_ofsx,pt.y-pen_ofsy,
  291.             graypat,wid,ht);
  292.         } break;
  293.     case TOOL_PAINT: {
  294.         POINT pt;  imagewin_getPosFromMos(win, &cp, &pt);
  295.         PIXEL pix; colsel_getPixel(&pix);
  296.         int csr;
  297.         MG_PushPtr(MOSICON_WAIT, &csr);
  298.         pic_beginUpDate(win->pic);
  299.         pic_paint(win->pic,pt.x,pt.y, &pix);
  300.         FRAME frUpdate;
  301.         pic_endUpDate(win->pic, &frUpdate);
  302.         MG_PopPtr(csr);
  303.         imagewin_updateScrPart(win, &frUpdate);
  304.         } break;
  305.     }
  306.   /* イベントループ */
  307.     BOOL fFirst = TRUE;
  308.     int ev_ret = NOERR;
  309.     for (;;)
  310.     {
  311.       // マウスボタンが放されたら終了
  312.         if (!fFirst && ev->what!=EVMOSDRAG && (ev->shift&SLEFTBTN)!=0)
  313.             break;
  314.       // PIC領域にカーソルがあれば、座標登録
  315.         else if (imagewin_PtInPic(win, &cp))
  316.         {
  317.           /* FIFOバッファへ座標を登録する関数 */
  318.             void push_p(int x,int y)
  319.             {
  320.                 POINT p;  p.x = x;  p.y = y;
  321.                 fifo_set(points,&p);
  322.             }
  323.           /* 処理種別ごとに分岐 */
  324.             switch (type)
  325.             {
  326.             case TOOL_KOSURI:
  327.             case TOOL_NIZIMI:
  328.                 push_p(cp.x, cp.y);
  329.                 break;
  330.             case TOOL_FPSET:
  331.             case TOOL_BOKASI:
  332.             case TOOL_SAND:
  333.                 if (ev_ret == NOERR)
  334.                     push_p(cp.x, cp.y);
  335.                 break;
  336.             case TOOL_FLINE:
  337.                 if (ev_ret == NOERR)
  338.                     do_line_cont(lastp.x,lastp.y,cp.x,cp.y, push_p);
  339.                 break;
  340.             }
  341.             lastp = cp;
  342.         }
  343.         if (!fifo_isEmpty(points))
  344.             _flushPointBuf(win,points,type);
  345.       // イベントセンス
  346.         MMI_iosense();
  347.         EVENT *pre_ev = ev;
  348.         if ((ev_ret = MMI_GetEvnt(EVMOSDRAG|EVMOSUP,&ev)) != NOERR)
  349.             ev = pre_ev;
  350.         else
  351.             fFirst = FALSE;
  352.         cp = *(POINT*)&ev->info;
  353.     }
  354.   /* 座標バッファのフラッシュ */
  355.     while (!fifo_isEmpty(points))
  356.         _flushPointBuf(win,points,type);
  357.     fifo_destroy(points);
  358.   /* 次に続くイベントループ処理のために、最後のイベントをキューに戻す */
  359.     EVENT evbuf;
  360.     evbuf = *ev;
  361.     MMI_SetEvnt(&evbuf);
  362.     return NOERR ;
  363. }
  364.  
  365. /*--------------------------------------------------------*/
  366. /*                 直線、矩形、矩形フィル                 */
  367. /*--------------------------------------------------------*/
  368.  
  369. static    int        draw_line(IMWIN *win, POINT *first, int type)
  370. /* first:最初のマウス座標 */
  371. /* type:0=直線  1=矩形  2=矩形フィル */
  372. {
  373.     imagewin_storeUndo(win);
  374.     int ret;
  375.     EVENT *ev, evbuf;
  376.     WINCLIP *pstackClip ;
  377.     FIFO *points;
  378.     POINT lastp;
  379.     int rub_x, rub_y;
  380.   /* FIFOバッファの作成 */
  381.     points = fifo_new(sizeof(POINT));
  382.     lastp = *first;
  383.     rub_x = lastp.x, rub_y = lastp.y;
  384.   /* クリップ枠の設定 */
  385.     RM_setOriginZero();
  386.     RM_setClipWinUser(win->win, &pstackClip) ; 
  387.   /* イベントループ */
  388.     for (;;)
  389.     {
  390.         int what,shift;
  391.         POINT *pt;
  392.       /* ラバー描画 */
  393.         MG_mosDisp(2);
  394.         if (type == 0)
  395.             { WGB_LINE(guiEgbPtr,lastp.x,lastp.y,rub_x,rub_y,
  396.                        MG_colorChange(WHITE), 4); }
  397.         else
  398.             { WGB_BOXLINE(guiEgbPtr,lastp.x,lastp.y,rub_x,rub_y,
  399.                           MG_colorChange(WHITE), 4); }
  400.         MG_mosDisp(3);
  401.       /* イベントセンス */
  402.         do {
  403.             MMI_iosense();
  404.         } while (MMI_GetEvnt(EVALL, &ev) != NOERR);
  405.       /* ラバー消去 */
  406.         MG_mosDisp(2);
  407.         if (type == 0)
  408.             { WGB_LINE(guiEgbPtr,lastp.x,lastp.y, rub_x, rub_y,
  409.                        MG_colorChange(WHITE), 4); }
  410.         else
  411.             { WGB_BOXLINE(guiEgbPtr,lastp.x,lastp.y, rub_x, rub_y,
  412.                           MG_colorChange(WHITE), 4); }
  413.         MG_mosDisp(3);
  414.       /* イベント種別、シフト状態、マウス座標を得る */
  415.         what  = ev->what;
  416.         shift = ev->shift;
  417.         pt    = (POINT *) &ev->info;
  418.       /* 次のラバー座標を得る */
  419.         rub_x = pt->x;
  420.         rub_y = pt->y;
  421.       /* 左ボタンがクリックされたら */
  422.         if (what == EVMOSDN && (shift & SLEFTBTN) != 0)
  423.         {
  424.             FRAME fr; RM_getWinUserFrame(win->win, &fr);
  425.             if (fr.X <= pt->x && pt->x <= fr.X2 &&
  426.                 fr.Y <= pt->y && pt->y <= fr.Y2)
  427.             {
  428.                 void pset(int x,int y)
  429.                 {
  430.                     POINT p;  p.x = x;  p.y = y;
  431.                     fifo_set(points,&p);
  432.                 }
  433.                 switch (type)
  434.                 {
  435.                 case 0:
  436.                     do_line(lastp.x,lastp.y,pt->x,pt->y, pset);
  437.                     while (!fifo_isEmpty(points))
  438.                         _flushPointBuf(win, points, TOOL_FPSET);
  439.                     break;
  440.                 case 1:
  441.                     do_boxline(lastp.x,lastp.y,pt->x,pt->y, pset);
  442.                     while (!fifo_isEmpty(points))
  443.                         _flushPointBuf(win, points, TOOL_FPSET);
  444.                     break;
  445.                 case 2:
  446.                     POINT mosp,imgp1,imgp2;
  447.                     FRAME updatefr,scrfr;
  448.                     PIXEL pixel;
  449.                     int min_y,max_y,i;
  450.                     colsel_getPixel(&pixel);
  451.                     mosp.x = lastp.x, mosp.y = lastp.y;
  452.                     imagewin_getPosFromMos(win, &mosp, &imgp1);
  453.                     mosp.x = pt->x,   mosp.y = pt->y;
  454.                     imagewin_getPosFromMos(win, &mosp, &imgp2);
  455.                     min_y = _min(imgp1.y, imgp2.y);
  456.                     max_y = _max(imgp1.y, imgp2.y);
  457.                   /* 画面更新の開始 */
  458.                     MG_mosDisp(2);
  459.                     pic_beginUpDate(win->pic);
  460.                   /* 矩形の描画 */
  461.                     for (i=min_y; i<=max_y; i++)
  462.                         pic_grayhline(win->pic,imgp1.x,imgp2.x,i,
  463.                                       pensel_getmix(),&pixel);
  464.                   /* 画面に画像の更新部分を転送 */
  465.                     pic_endUpDate(win->pic, &updatefr);
  466.                     imagewin_updateScrPart(win, &updatefr);
  467.                   /* 画面更新の終了 */
  468.                     MG_mosDisp(3);
  469.                 }
  470.                 lastp = *pt;
  471.                 if (type != 0)
  472.                     break;
  473.             }
  474.         }
  475.       /* 右ボタンがクリックされたら */
  476.         else if (what == EVMOSDN && (shift & SRIGHTBTN) != 0)
  477.         {
  478.             break;
  479.         }
  480.     }
  481.   /* クリップ枠の復帰 */
  482.     RM_resetClipWinUser(pstackClip) ;
  483.     RM_recoverOrigin();
  484.   /* FIFOバッファの消滅 */
  485.     fifo_destroy(points);
  486.   /* 次に続くイベントループ処理のために、マウス左ボタンの EVMOSUP イベントを
  487.      キューに積む */
  488.     evbuf = *ev;
  489.     evbuf.what = EVMOSUP;
  490.     evbuf.shift = (evbuf.shift & (~SRIGHTBTN)) | SLEFTBTN;
  491.     MMI_SetEvnt(&evbuf);
  492.     return NOERR ;
  493. }
  494.